﻿using MathNet.Symbolics;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

using Expr = MathNet.Symbolics.SymbolicExpression;

namespace NumericalAnalysis.DataInterpolation
{
    public static class NumericalService
    {

        /// <summary>
        /// 数列生成
        /// </summary>
        /// <param name="stNum"></param>
        /// <param name="edNum"></param>
        /// <param name="step"></param>
        /// <returns></returns>
        public static List<double> LinSpace(double stNum, double edNum, double step)
        {
            List<double> doubles = new List<double>();
            for (double i = stNum; i <= edNum; i += step)
            {
                doubles.Add(i);
            }
            return doubles;
        }

        /// <summary>
        /// 根据函数计算2D
        /// </summary>
        /// <param name="func"></param>
        /// <param name="vectors"></param>
        /// <returns></returns>
        public static IList<Tuple<double, double>> CalcByFunc(Func<double, double> func, IList<Tuple<double, double>> vectors)
        {
            var newVecs = new List<Tuple<double, double>>();
            foreach (var vector in vectors)
            {
                double vecX = vector.Item1;
                double vecY = func(vecX);
                var newVec = new Tuple<double, double>(vecX, vecY);
                newVecs.Add(newVec);
            }
            return newVecs;
        }

        /// <summary>
        /// 根据函数计算
        /// </summary>
        /// <param name="func"></param>
        /// <param name="array"></param>
        /// <returns></returns>
        public static IList<Tuple<double, double>> CalcByFunc(Func<double, double> func, IList<double> array)
        {

            var newVecs = new List<Tuple<double, double>>();
            foreach (var num in array)
            {
                double vecX = num;
                double vecY = func(vecX);
                var newVec = new Tuple<double, double>(vecX, vecY);
                newVecs.Add(newVec);
            }
            return newVecs;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="expression">表达式</param>
        /// <param name="variables"> key为变量符号 ， value 为其取值列 {t,[1.0,5.5,1.42,4.2] } {x,[...]} </param>
        /// <returns></returns>
        public static IList<double> CalculateBy(this Expr expression, Dictionary<string, IEnumerable<double>> variables)
        {
            List<double> yValues = new List<double>();

            int minCount = variables.Values.OrderBy(v => v.Count()).First().Count();
            int count = 0;
            while (count <  minCount)
            {
                var symbols = new Dictionary<string, FloatingPoint>();
                foreach (var variable in variables)
                {
                    var sym = variable.Key;
                    var symValues = variable.Value.ToList();
                    var symValue = symValues[count];
                    symbols.Add(sym, symValue);
                }
                double yValue = expression.Evaluate(symbols).RealValue;
                yValues.Add(yValue);

                count++;
            }
 
            return yValues;
        }

      

    }
}
